package com.tianhao.luo.nouse.product;

import java.io.*;

/**
 * 一个产品对象
 * 如果这个产品类需要被克隆，那么这个类就必须实现Cloneable接口；这个接口只是一个标识。clone方法是Object类提供的。
 * 当这个对象有一个可变属性类作为属性，那么这是可变属性类也要实现Cloneable接口，并重写clone方法
 * @author tianhao.luo
 * @date 2019/12/13 14:45
 */
public class Product implements Cloneable,Serializable{
    private static final long serialVersionUID = 42L;
    private String productName;
    private String companyName;
    private String part1;
    private String part2;
    private String part3;
    private String part4;
    // ... 这是一个复杂对象，省略一部分属性
    private BaseInfo baseInfo;

    public Product() {
    }

    public BaseInfo getBaseInfo() {
        return baseInfo;
    }

    public void setBaseInfo(BaseInfo baseInfo) {
        this.baseInfo = baseInfo;
    }

    /**
     * 对引用类型进行拷贝
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    public Product clone() throws CloneNotSupportedException {
        // v1
        //把可变属性也克隆一份
//        BaseInfo clone = this.baseInfo.clone();
//        Product clone1 = (Product)super.clone();
//        //当该对象克隆完成，将可变属性的备份给恢复
//        clone1.setBaseInfo(clone);
//        return clone1;

        // v2
        // 实现反序列化之后，也是新的对象
        try {
            //将对象写入到流中
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(byteArrayOutputStream);
            oos.writeObject(this);
            oos.close();
            //再从流中读取出对象，并实例化
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream);
            Product product = (Product) ois.readObject();
            return product;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String toString() {
        return super.hashCode()+"   ]Product{" +
                "productName='" + productName + '\'' +
                ", companyName='" + companyName + '\'' +
                ", part1='" + part1 + '\'' +
                ", part2='" + part2 + '\'' +
                ", part3='" + part3 + '\'' +
                ", part4='" + part4 + '\'' +
                ", baseInfo=" + baseInfo +
                '}';
    }

    public Product(String productName, String companyName,
                   String part1, String part2, String part3,
                   String part4, BaseInfo baseInfo) {
        this.productName = productName;
        this.companyName = companyName;
        this.part1 = part1;
        this.part2 = part2;
        this.part3 = part3;
        this.part4 = part4;
        this.baseInfo = baseInfo;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public String getCompanyName() {
        return companyName;
    }

    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }

    public String getPart1() {
        return part1;
    }

    public void setPart1(String part1) {
        this.part1 = part1;
    }

    public String getPart2() {
        return part2;
    }

    public void setPart2(String part2) {
        this.part2 = part2;
    }

    public String getPart3() {
        return part3;
    }

    public void setPart3(String part3) {
        this.part3 = part3;
    }

    public String getPart4() {
        return part4;
    }

    public void setPart4(String part4) {
        this.part4 = part4;
    }
}
